﻿//===============================================================================
// Jammer.NET Development Library
// Jmr.Compression
//===============================================================================
// Copyright © Junaid Fakhruddin, Matthew Leedham and Randolph Cabral.  
// All rights reserved.
//===============================================================================
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.Zip.Compression;

namespace Jmr.Compression
{
	/// <summary>
	/// Wrapper for compression/decompression methods.
	/// </summary>
	public class Utility
	{
		/// <summary>
		/// Converts a stream into a GZip compressed stream.
		/// </summary>
		/// <param name="stream">Stream to compress.</param>
		/// <returns>Compressed stream.</returns>
		public static MemoryStream CompressGZip(Stream stream)
		{
			var retval = new MemoryStream();
			stream.Seek(0L, SeekOrigin.Begin);
			var reader = new BinaryReader(stream);
			var rawbytes = reader.ReadBytes(Convert.ToInt32(stream.Length));
			var gzipstream = new GZipOutputStream(retval);
			gzipstream.Write(rawbytes, 0, rawbytes.Length);
			gzipstream.Finish();
			return retval;
		}

		/// <summary>
		/// Converts a GZip compressed stream into a decompressed stream.
		/// </summary>
		/// <param name="stream">Stream to decompress.</param>
		/// <returns>Decompressed stream.</returns>
		public static MemoryStream DecompressGZip(Stream stream)
		{
			var retval = new MemoryStream();
			var gzipstream = new GZipInputStream(stream);
			var buffer = new byte[4096];
			StreamUtils.Copy(gzipstream, retval, buffer);
			return retval;
		}

		/// <summary>
		/// Converts a stream into a Headerless compressed stream.
		/// </summary>
		/// <param name="stream">Stream to compress.</param>
		/// <returns>Compressed stream.</returns>
		public static MemoryStream CompressHeaderless(Stream stream)
		{
			var retval = new MemoryStream();
			stream.Seek(0L, SeekOrigin.Begin);
			var reader = new BinaryReader(stream);
			var rawbytes = reader.ReadBytes(Convert.ToInt32(stream.Length));

			var deflater = new Deflater(-1, true);
			using (DeflaterOutputStream outStream = new DeflaterOutputStream(retval, deflater))
			{
				outStream.IsStreamOwner = false;
				outStream.Write(rawbytes, 0, rawbytes.Length);
				outStream.Flush();
				outStream.Finish();
			}
			return retval;
		}

		/// <summary>
		/// Converts a Headerless compressed stream into a decompressed stream.
		/// </summary>
		/// <param name="stream">Stream to decompress.</param>
		/// <returns>Decompressed stream.</returns>
		public static MemoryStream DecompressHeaderless(Stream stream)
		{
			var retval = new MemoryStream();
			stream.Seek(0L, SeekOrigin.Begin);
			Inflater inflater = new Inflater(true);
			InflaterInputStream inStream = new InflaterInputStream(stream, inflater);
			var buffer = new byte[40960];
			int currentIndex = 0;
			int count = buffer.Length;

			while (true)
			{
				int bytesRead = inStream.Read(buffer, 0, buffer.Length);
				if (bytesRead <= 0)
					break;
				retval.Write(buffer, 0, bytesRead);
				currentIndex += bytesRead;
			}
			retval.Seek(0, 0);
			return retval;
		}
	}
}
